package com.otitan.forest.right.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.otitan.forest.right.constant.StaticConstant;
import com.otitan.forest.right.dto.LoginDto;
import com.otitan.forest.right.dto.UpdatePwdDto;
import com.otitan.forest.right.entity.SysRoleEntity;
import com.otitan.forest.right.entity.SysUserEntity;
import com.otitan.forest.right.entity.SysUserRoleRelationEntity;
import com.otitan.forest.right.exception.LoginException;
import com.otitan.forest.right.mapper.SysUserMapper;
import com.otitan.forest.right.service.SysOrganizationService;
import com.otitan.forest.right.service.SysRoleService;
import com.otitan.forest.right.service.SysUserRoleRelationService;
import com.otitan.forest.right.service.SysUserService;
import com.otitan.forest.right.util.CommonUtil;
import com.otitan.webapp.framework.basepro.exception.BusinessException;
import com.otitan.webapp.framework.basepro.model.DataResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service("sysUserService")
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserEntity> implements SysUserService {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysOrganizationService sysOrganizationService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysUserRoleRelationService sysUserRoleRelationService;

    @Value("${forest-right.exe.encrypt_and_decode_path}")
    private String encryptAndDecodePath;

    @Override
    public SysUserEntity findByUserName(String username) {
        return sysUserMapper.findByUserName(username);
    }

    @Override
    public DataResult zhlyLogin(LoginDto dto) {
        if (!StaticConstant.FORESTRY_SYSTEM.equals(dto.getServiceId())) {
            return DataResult.fail("用户名不存在！");
        }
        if (StrUtil.isEmpty(dto.getPassword()) || StrUtil.isEmpty(dto.getUsername())) {
            return DataResult.fail("用户名或密码错误！");
        }

        SysUserEntity user = findByUserName(dto.getUsername());
        if (user == null) {
            return DataResult.fail("用户名不存在！");
        }
        String pwd = "";
        if ("2".equals(dto.getType())) {
            // 密文
            pwd = CommonUtil.decodePassword(encryptAndDecodePath, dto.getPassword());
        } else {
            // 文明
            pwd = dto.getPassword();
        }
        SysUserEntity entity = new SysUserEntity();
        entity.setPassword(pwd);
        entity.setUsername(dto.getUsername());
        return login(entity);
    }

    @Override
    public DataResult updatePwdByUsername(UpdatePwdDto updatePwdDto) {
        if (StringUtils.isBlank(updatePwdDto.getUserName())) {
            throw new BusinessException("用户名不可为空！");
        }
        if (StringUtils.isBlank(updatePwdDto.getOldPassword()) || StringUtils.isBlank(updatePwdDto.getNewPassword())) {
            throw new BusinessException("新密码或旧密码不可为空！");
        }
        SysUserEntity entity = sysUserMapper.findByUserName(updatePwdDto.getUserName());
        String salt = StaticConstant.SALT;
        String oldPasswordStr = new SimpleHash("MD5", updatePwdDto.getOldPassword(), salt, 1024).toHex();
        if (!entity.getPassword().equals(oldPasswordStr)) {
            throw new BusinessException("旧密码输入错误，请重新输入！");
        }

        String newPassword = new SimpleHash("MD5", updatePwdDto.getNewPassword(), salt, 1024).toHex();
        String userName = updatePwdDto.getUserName();
        Map<String, String> map = new HashMap<>();
        map.put("userName", userName);
        map.put("newPassword", newPassword);
        sysUserMapper.updatePwdByUsername(map);
        return DataResult.success();
    }


    @Override
    public DataResult login(SysUserEntity sysUser) {
        SysUserEntity user = findByUserName(sysUser.getUsername());
        if (user == null) {
            throw new LoginException("用户名或密码错误");
        }
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(sysUser.getUsername(), sysUser.getPassword());
        Serializable tokenId = null;
        try {
            SecurityUtils.getSubject().login(usernamePasswordToken);
            SecurityUtils.getSubject().getSession().setTimeout(1000 * 60 * 60 * 6);
            SysUserEntity sessionUserBean = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
            if (sessionUserBean == null) {
                throw new LoginException("用户名或密码错误");
            }
            Subject subject = SecurityUtils.getSubject();
            tokenId = subject.getSession().getId();
        } catch (Exception e) {
            log.error("密码错误！");
            throw new LoginException("用户名或密码错误");
        }
        return DataResult.success(tokenId);
    }

    @Override
    public SysUserEntity packagePassword(SysUserEntity userEntity) {
        Map<String, Object> map = new HashMap<>();
        map.put("username", userEntity.getUsername());
        map.put("is_delete", 0);
        List<SysUserEntity> sysUserEntities = listByMap(map);
        if (sysUserEntities != null && sysUserEntities.size() > 0) {
            throw new BusinessException("用户名不可重复！");
        }
        if (userEntity.getPassword() == null) {
            userEntity.setPassword(StaticConstant.PASSWORD);
        }
        String salt = StaticConstant.SALT;
        String newPassword = new SimpleHash("MD5", userEntity.getPassword(), salt, 1024).toHex();
        userEntity.setPassword(newPassword);
        return userEntity;
    }

    @Override
    public void checkUpdateUser(SysUserEntity userEntity) {
        if (userEntity == null) {
            throw new BusinessException("用户信息不可为空！");
        }
        if (userEntity.getUsername() != null) {
            LambdaQueryWrapper<SysUserEntity> queryWrapper = Wrappers.lambdaQuery();
            //查询条件示例
            queryWrapper.eq(SysUserEntity::getIsDelete, 0);
            queryWrapper.eq(SysUserEntity::getUsername, userEntity.getUsername());
            SysUserEntity sysUserEntity = getOne(queryWrapper);

            if (sysUserEntity != null && !userEntity.getId().equals(sysUserEntity.getId())) {
                throw new BusinessException("用户名不可重复！");
            }
        }
    }

    @Override
    public List<SysUserEntity> findByGroupId(String groupId) {
        LambdaQueryWrapper<SysUserEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(SysUserEntity::getGroupId, groupId);
        List<SysUserEntity> sysUserEntities = list(queryWrapper);
        return sysUserEntities;
    }

    @Override
    public DataResult dataSynchronization(String uuid) {
        try {
            if ("otitan-admin".equals(uuid)) {
                // 删除之前同步的用户信息 和 用户角色关联信息
                sysUserMapper.delUserRoleInformation();
                sysUserMapper.delPreviouslySyncedUserInformation();

                List<SysUserEntity> userList = this.list();
                Set<String> usernameSet = userList.stream().map(SysUserEntity::getUsername).collect(Collectors.toSet());


                // // 查询一期用户信息
                // List<SysUserEntity> sysUserEntities1 = sysUserMapper.queryUserInformationOfSmartForestrySystem1();
                // // 处理一期用户信息
                // processFirstPhaseData(sysUserEntities1);
                List<SysUserEntity> sysUserEntities1 = new ArrayList<>();

                // 查询二期用户信息
                List<SysUserEntity> sysUserEntities2 = sysUserMapper.queryUserInformationOfSmartForestrySystem2();
                // 处理二期用户信息
                processTheSecondPhaseData(sysUserEntities2);

                // 合集
                sysUserEntities1.addAll(sysUserEntities2);

                // 查询系统角色
                List<SysRoleEntity> list = sysRoleService.list();
                Map<String, String> roleMap = list.stream().collect(Collectors.toMap(SysRoleEntity::getRole, SysRoleEntity::getId));
                // 用户角色关系
                List<SysUserRoleRelationEntity> relationEntityList = new ArrayList<>();
                Iterator<SysUserEntity> iterator = sysUserEntities1.iterator();
                int index = 0;
                while (iterator.hasNext()) {
                    SysUserEntity next = iterator.next();
                    index++;
                    if (usernameSet.contains(next.getUsername())) {
                        iterator.remove();
                    } else {
                        next.setId("zhly" + index);
                        usernameSet.add(next.getUsername());
                        if (next.getUsername().contains("admin")) {
                            relationEntityList.add(new SysUserRoleRelationEntity(next.getId(), roleMap.get("admin")));
                        } else {
                            if (next.getBelongGroupLevel() == 1) {
                                relationEntityList.add(new SysUserRoleRelationEntity(next.getId(), roleMap.get("audit")));
                            } else if (next.getBelongGroupLevel() == 2) {
                                relationEntityList.add(new SysUserRoleRelationEntity(next.getId(), roleMap.get("audit")));
                            } else {
                                relationEntityList.add(new SysUserRoleRelationEntity(next.getId(), roleMap.get("ordinary")));
                            }
                        }
                    }
                }

                String data = JSONArray.toJSONString(sysUserEntities1, SerializerFeature.WriteMapNullValue);
                log.debug("处理后的结果：{}", data);
                int batchSize = (sysUserEntities1.size() / 200) + 1;
                // 保存用户信息
                this.saveBatch(sysUserEntities1, batchSize);

                // 保存用户角色关联信息
                sysUserRoleRelationService.saveBatch(relationEntityList, batchSize);
                return DataResult.success(data);
            } else {
                return DataResult.success("恶意入侵");
            }
        } catch (Exception e) {
            return DataResult.fail(e.getMessage());
        }
    }

    /**
     * 处理一期用户数据
     *
     * @param []
     * @return void
     * @throws
     * @author jiachangsen
     * @date 2020/08/24 09:23
     */
    private void processFirstPhaseData(List<SysUserEntity> sysUserEntities) {
        if (CollUtil.isNotEmpty(sysUserEntities)) {
            Iterator<SysUserEntity> iterator = sysUserEntities.iterator();
            while (iterator.hasNext()) {
                SysUserEntity next = iterator.next();
                if (StrUtil.isNotBlank(next.getGroupId())) {
                    if (next.getBelongGroupLevel() == 0) {
                        next.setBelongGroupLevel(1);
                        String groupId = next.getGroupId().substring(0, 2) + "0000";
                        next.setProvince(groupId);
                        next.setGroupId(groupId);
                    } else if (next.getBelongGroupLevel() == 1) {
                        next.setBelongGroupLevel(2);
                        next.setProvince(next.getGroupId().substring(0, 2) + "0000");
                        next.setCity(next.getGroupId() + "00");
                    } else if (next.getBelongGroupLevel() == 2) {
                        next.setGroupId(next.getGroupId() + "00");
                    } else if (next.getBelongGroupLevel() == 2) {
                        next.setBelongGroupLevel(3);
                        next.setProvince(next.getGroupId().substring(0, 2) + "0000");
                        next.setCity(next.getGroupId().substring(0, 4) + "00");
                        next.setCounty(next.getGroupId());
                    } else if (next.getBelongGroupLevel() == 3) {
                        next.setBelongGroupLevel(3);
                        next.setProvince(next.getGroupId().substring(0, 2) + "0000");
                        next.setCity(next.getGroupId().substring(0, 4) + "00");
                        next.setCounty(next.getGroupId().substring(0, 6));
                        // next.setTown(next.getGroupId());
                    } else {
                        next.setBelongGroupLevel(3);
                        next.setProvince(next.getGroupId().substring(0, 2) + "0000");
                        next.setCity(next.getGroupId().substring(0, 4) + "00");
                        next.setCounty(next.getGroupId().substring(0, 6));
                    }
                } else {
                    iterator.remove();
                }
            }
        }
    }

    /**
     * 处理二期用户数据
     *
     * @param []
     * @return void
     * @throws
     * @author jiachangsen
     * @date 2020/08/24 09:23
     */
    private void processTheSecondPhaseData(List<SysUserEntity> sysUserEntities) {
        if (CollUtil.isNotEmpty(sysUserEntities)) {
            Iterator<SysUserEntity> iterator = sysUserEntities.iterator();
            while (iterator.hasNext()) {
                SysUserEntity next = iterator.next();
                // 密码转换
                String newPassword = CommonUtil.zhlyPwdToNowPwd(encryptAndDecodePath, next.getPassword());
                next.setPassword(newPassword);
                if (StrUtil.isNotBlank(next.getGroupId())) {
                    if (next.getGroupId().endsWith("0000")) {
                        next.setBelongGroupLevel(1);
                        next.setProvince(next.getGroupId());
                    } else if (next.getGroupId().endsWith("00")) {
                        next.setBelongGroupLevel(2);
                        next.setProvince(next.getGroupId().substring(0, 2) + "0000");
                        next.setCity(next.getGroupId());
                    } else {
                        next.setBelongGroupLevel(3);
                        next.setProvince(next.getGroupId().substring(0, 2) + "0000");
                        next.setCity(next.getGroupId().substring(0, 4) + "00");
                        next.setCounty(next.getGroupId());
                    }
                } else {
                    iterator.remove();
                }
            }
        }
    }
}